package com.smedi.ismedi.authoritymanagement.core.application.service.impl;

import com.smedi.ismedi.authoritymanagement.core.application.command.AccountBasicCommand;
import com.smedi.ismedi.authoritymanagement.core.application.command.ChangeMobileCommand;
import com.smedi.ismedi.authoritymanagement.core.application.command.ChangePasswordCommand;
import com.smedi.ismedi.authoritymanagement.core.application.query.vo.MobileVerificationCodeVo;
import com.smedi.ismedi.authoritymanagement.core.application.service.AccountBasicApplicationService;
import com.smedi.ismedi.authoritymanagement.core.domain.aggregatemodel.AccountBasic;
import com.smedi.ismedi.authoritymanagement.core.domain.repository.VerificationCodeRepository;
import com.smedi.ismedi.authoritymanagement.core.domain.service.AccountBasicDomainService;
import com.smedi.ismedi.authoritymanagement.core.infrastructure.constant.ConstantField;
import com.smedi.ismedi.authoritymanagement.core.infrastructure.constant.CustomError;
import com.smedi.ismedi.authoritymanagement.core.port.adapter.service.PersonnelRemoteApiService;
import com.smedi.ismedi.web.starter.exception.LogicException;
import com.smedi.ismedi.web.starter.util.DozerUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

/**
 * @Author: xulinjun
 * @Date: 2021-7-2 10:41
 */
@Slf4j
@Service
@AllArgsConstructor
public class AccountBasicApplicationServiceImpl implements AccountBasicApplicationService {
    private final DozerUtil dozerUtil;

    private final VerificationCodeRepository verificationCodeRepository;

    private final AccountBasicDomainService accountBasicDomainService;

    private final PersonnelRemoteApiService personnelRemoteApiService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AccountBasic generateAccount(AccountBasicCommand userBasicCommand) {
        AccountBasic userBasic = dozerUtil.convertor(userBasicCommand, AccountBasic.class);
        return accountBasicDomainService.generateAccountBasic(userBasic);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changePassword(ChangePasswordCommand changePasswordCommand) {
        accountBasicDomainService.changePassword(changePasswordCommand.getUserKey(), changePasswordCommand.getPersonId(), changePasswordCommand.getPassword(), changePasswordCommand.getNewPassword());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resetPassword(String callAccount, String newPassword) {
        // 获取用户
        AccountBasic accountBasic = accountBasicDomainService.getAccountBasic(callAccount);
        // 判断当前重置操作是否有效
        String key = ConstantField.waitingResetPasswordPath + accountBasic.getMobile();
        if (verificationCodeRepository.hasMobileSession(key)) {
            // 重置密码
            accountBasicDomainService.resetPassword(accountBasic.getUserId(), newPassword);

            // 移除有效期
            verificationCodeRepository.deleteMobileSession(key);
        } else {
            throw LogicException.raise(CustomError.RESET_PASSWORD_OVERTIME);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeMobile(ChangeMobileCommand changeMobileCommand) {
        accountBasicDomainService.changeMobile(changeMobileCommand.getMobile(), changeMobileCommand.getPersonId());
    }

    @Override
    public MobileVerificationCodeVo generateVerificationCode(String callAccount) {
        // 获取用户手机号
        String mobile = accountBasicDomainService.getAccountMobile(callAccount);
        // 生成6位验证码
        String verificationCode = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
        log.info("mobile: {}, verificationCode: {}", mobile, verificationCode);

        // 讲验证码存放至Redis上
        String key = ConstantField.verificationCodePath + mobile;
        if (verificationCodeRepository.hasMobileSession(key)) {
            verificationCodeRepository.deleteMobileSession(key);
        } else {
            verificationCodeRepository.setResetPasswordSession(key, verificationCode, ConstantField.verificationCodeLive); // 设置有效期
        }

        return new MobileVerificationCodeVo().setVerificationCode(verificationCode)
                .setMobile(mobile)
                .setMinutes(ConstantField.verificationCodeLive / 60);
    }

    @Override
    public void submitVerificationCode(String callAccount, String verificationCode) {
        // 验证码校验
        if (StringUtils.isEmpty(verificationCode)) {
            throw LogicException.raise(CustomError.VERIFICATION_CODE_EMPTY);
        }

        // 获取用户手机号
        String mobile = accountBasicDomainService.getAccountMobile(callAccount);

        // 获取Redis上的验证码
        String key = ConstantField.verificationCodePath + mobile;
        verificationCodeRepository.submit(key, verificationCode, mobile);
    }

    @Override
    public void enable(Long personId) {
        accountBasicDomainService.editUserStatus(personId, true);
    }

    @Override
    public void disable(Long personId) {
        accountBasicDomainService.editUserStatus(personId, false);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAccount(Long personId) {
        accountBasicDomainService.deleteAccount(personId);

        personnelRemoteApiService.deletePersonBasicAndAllAssignments(personId);
    }

    @Override
    public void deleteAccountOnly(Long personId) {
        accountBasicDomainService.deleteAccount(personId);
    }
}
